const {MUtils} = require("./MUtils");

/**
 * 定时任务工具类
 */
class JobUtil {

    /**
     * 任务
     *
     * @type {{}}
     */
    static JOBS = {};

    /**
     * 任务类型
     *
     * @type {{}}
     */
    static JOB_TYPE = {

        /**
         * 检查登录状态
         */
        CHECK_LOGIN_STATUS: "check_login_status",

        /**
         * 刷新赛事列表
         */
        REFRESH_GAME_LIST: "refresh_game_list",

        /**
         * 刷新已选注单赔率
         */
        REFRESH_GAME_ODDS: "refresh_game_odds",

        /**
         * 刷新平博缓存
         */
        REFRESH_PB_CACHE: "refresh_pb_cache",

        /**
         * 清除投注中产生的失效的key
         */
        CLEAR_INVALID_BET_KEY: "clear_invalid_bet_key",

        /**
         * 刷新映射缓存
         */
        REFRESH_GAME_MAPPING_CACHE: "refresh_game_mapping_cache",

        /**
         * 自动重启扫描
         */
        AUTO_RETRY_START_BET: "AUTO_RETRY_START_BET",

        /**
         * 自动刷新平博窗口
         */
        AUTO_REFRESH_PB_WINDOW: "AUTO_REFRESH_PB_WINDOW",
    };

    /**
     * 放置任务
     *
     * @param name
     * @param jobIndex
     * @param jobType   任务类型：1-setTimeout，2-setInterval
     */
    static putJob(name, jobIndex, jobType) {
        // 清除原任务
        JobUtil.clearJob(name);
        // 设置新任务
        JobUtil.JOBS[name] = {
            jobIndex: jobIndex,
            jobType: jobType
        };
    }

    /**
     * 清除任务
     *
     * @param name
     */
    static clearJob(name) {
        const existsJob = JobUtil.JOBS[name];
        if (existsJob != null) {
            const jobIndex = existsJob.jobIndex;
            const jobType = existsJob.jobType;
            if (jobType === 1) {
                clearTimeout(jobIndex);
            } else if (jobType === 2) {
                clearInterval(jobIndex);
            }
        }
    }

    /**
     * 执行setTimeout
     *
     * @param name      任务名称
     * @param timeout   延迟
     * @param handler   处理函数
     */
    static startTimeout(name, timeout, handler) {
        if (timeout == null) {
            throw new ReferenceError("timeout不能为空！");
        }

        // 清空原任务
        JobUtil.clearJob(name);

        // 执行新任务
        const index = setTimeout(function () {
            // console.log(`执行任务-${name}`);
            handler();
        }, timeout);

        JobUtil.putJob(name, index, 1);
    }

    /**
     * 执行setInterval
     *
     * @param name          任务名称
     * @param timeout       延迟
     * @param handler       处理函数
     */
    static startInterval(name, timeout, handler) {
        if (timeout == null) {
            throw new ReferenceError("timeout不能为空！");
        }

        // 清空原任务
        JobUtil.clearJob(name);

        // 执行新任务
        const index = setInterval(function () {
            // console.log(`执行任务-${name}`);
            handler();
        }, timeout);
        JobUtil.putJob(name, index, 2);
    }

    /**
     * 延迟循环调用
     *
     * @param delay         延迟时间（ms）
     * @param retry         重试次数
     * @param handler
     * @return {Promise<DelayJobResult>}
     */
    static startRetryInvoke(delay, retry, handler) {
        return new Promise(resolve => delayInvoke(delay, retry, 0, handler, resolve));
    }

    /**
     * 获取随机整数
     *
     * @param min
     * @param max
     * @returns {number}
     */
    static getRandomInt(min, max) {
        return MUtils.getRandomInt(min, max);
    }
}

/**
 * 延迟调用
 *
 * @param delay     延迟时间
 * @param retry     尝试次数
 * @param count     当前次数
 * @param handler   处理函数
 * @param resolve   回调函数
 */
function delayInvoke(delay, retry, count, handler, resolve) {
    setTimeout(async function () {
        if (count >= retry) {
            // 执行超时
            const result = new DelayJobResult(false, '执行超时');
            resolve(result);
        } else {
            const data = await handler();
            if (data != null) {
                // 执行成功
                const result = new DelayJobResult(true, '执行成功！', data);
                resolve(result);
            } else {
                // 执行失败，继续尝试
                ++count;
                delayInvoke(delay, retry, count, handler, resolve);
            }
        }
    }, delay);
}

/**
 * 延迟任务处理 结果
 */
class DelayJobResult {

    /**
     * @param status    状态:true/false
     * @param message   错误消息
     * @param data      数据
     */
    constructor(status, message, data) {
        this.status = status;
        this.message = message;
        this.data = data;
    }
}

module.exports = {
    JobUtil,
    DelayJobResult
};